package com.yx.cloud.product.gyro;

import com.iot.common.utils.LogUtils;
import com.iot.product.sweeper.bean.CleanRecord;
import com.iot.product.sweeper.bean.Map;
import com.iot.product.sweeper.bean.MapInfo;
import com.iot.product.sweeper.bean.Path;
import com.iot.product.sweeper.bean.PathPoint;
import com.iot.product.sweeper.bean.Sweeper;
import com.yx.cloud.product.gyro.bean.GyroMapInfo;
import com.yx.cloud.product.laser.tuyapublic.ParseResult;
import com.yx.cloud.utils.PathUtils;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.UnsupportedEncodingException;
import java.util.Arrays;

public class GyroMapDataParser {
    public static final String TAG = "GyroMapDataParser";

    private static int TYPE_CURRENT = 0;//00，当前点   用于路径
    private static int TYPE_WALL = 1;   //01，障碍点
    private static int TYPE_CLEANED = 2;//02，已清扫点
    private static int TYPE_POWER = 3;  //03，充电桩
    private static int TYPE_UNUSE = 4;  //04，（预留）

    public static ParseResult parseMapData(Map map, byte[] data) {
        //{"width":4,"hight":1,"map_origin":[128,128],"robot_pos":[128,128],"clean_time_s":0,"map_data":"AA=="}
        String mapDataUnzip = new String(data);
        JSONObject mapDataObject;
        try {
            mapDataObject = new JSONObject(mapDataUnzip);

            int mapId = 0;
            if (mapDataObject.has("map_id")) {
                mapId = mapDataObject.getInt("map_id");
            }

            int mapWidth = 0, mapHeight = 0;
            if (mapDataObject.has("width")) {
                mapWidth = mapDataObject.getInt("width");
            }

            if (mapDataObject.has("hight")) {
                mapHeight = mapDataObject.getInt("hight");
            }

            if (mapWidth <= 0 || mapHeight <= 0) {
                return new ParseResult(ParseResult.MSG_PARSE_FAIL_DATA_ERROR);
            }

            JSONArray mapOrigin = null;
            int originX, originY;
            if (mapDataObject.has("map_origin")) {
                mapOrigin = mapDataObject.getJSONArray("map_origin");
            }
            if (mapOrigin != null) {
                originX = mapOrigin.getInt(0);
                originY = mapOrigin.getInt(1);
            }

            JSONArray robotPos = null;
            int robotX, robotY;
            if (mapDataObject.has("robot_pos")) {
                robotPos = mapDataObject.getJSONArray("robot_pos");
            }
            if (robotPos != null) {
                robotX = robotPos.getInt(0);
                robotY = robotPos.getInt(1);
            }

            int cleanTime = 0;
            if(mapDataObject.has("clean_time_s")){
                cleanTime = mapDataObject.getInt("clean_time_s");
            }

            byte[] byteData = null;
            String mapDataStr = null;
            if (mapDataObject.has("map_data")) {
                mapDataStr = mapDataObject.getString("map_data");
            }
            if (mapDataStr == null) {
                return new ParseResult(ParseResult.MSG_PARSE_FAIL_DATA_ERROR);
            }

            try {
                byteData = mapDataStr.getBytes("UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
                return new ParseResult(ParseResult.MSG_PARSE_FAIL_DATA_ERROR);
            }

            GyroMapInfo mapInfo = (GyroMapInfo) map.getMap();
            mapInfo.cleanTime = cleanTime / 60;
            mapInfo.mapType = MapInfo.MAP_TYPE_GYRO;
            mapInfo.mapId = mapId;
            Path path = map.getPath();
            Sweeper device = map.getSweeper();
            //转换地图数据 加上裁剪
            convertMapData(byteData,mapWidth,mapHeight,mapInfo);



            JSONArray pathData = null;
            if (mapDataObject.has("path_data")) {
                pathData = mapDataObject.getJSONArray("path_data");
                path.clear();
                for (int i = 0; i < pathData.length(); i++) {
                    JSONArray pathPos = pathData.getJSONArray(i);
                    int x, y, t = PathPoint.TYPE_CLEAN;
                    if (pathPos != null) {
                        x = pathPos.getInt(0);
                        y = pathPos.getInt(1);
                        if (pathPos.length() > 2) {
                            t = pathPos.getInt(2);
                            if (t == 1) {
                                t = PathPoint.TYPE_CLEAN;
                            }
                        }
                        setPathPoint(path, x, y, t);
                    }
                }
                //转换路径数据 加上裁剪
                convertPath(mapInfo, path, device);
            }

        } catch (JSONException e) {
            e.printStackTrace();
        }

        return new ParseResult(ParseResult.MSG_PARSE_SUCCESS);
    }

    private static void setPathPoint(Path path, int x, int y, int t) {
        path.pathPoints.add(new PathPoint((float) x + 0.5f, (float) y + 0.5f, t));
    }

    //计算地图范围
    public static void convertMapData(byte[] byteData, int mapWidth, int mapHeight, GyroMapInfo mapInfo) {
        double cleanArea = 0;
        int[] mapArray = new int[byteData.length];
        for (int i = 0; i < byteData.length; i++) {
            int value = byteData[i] - 48;
            if (value == 0) {
                mapArray[i] = MapInfo.TYPE_ORIGIN;
                cleanArea += 0.02175625;
            } else if (value == 1) {
                mapArray[i] = MapInfo.TYPE_WALL;
            } else if (value == 3) {
                mapArray[i] = MapInfo.TYPE_NONE;
            }
        }
        LogUtils.lm(mapArray, mapWidth);

        int minX = mapInfo.left;
        int maxX = mapInfo.right;
        int minY = mapInfo.top;
        int maxY = mapInfo.bottom;
        //设置x y的最大跨度 需要根据最大跨度缩放
        for (int i = 0; i < mapArray.length; i++) {
            int x = i % mapWidth;
            int y = i / mapWidth;

            if (mapArray[i] == MapInfo.TYPE_NONE) {
                continue;
            }

            if (x < minX) {
                minX = x;
            }
            if (x > maxX) {
                maxX = x;
            }

            if (y < minY) {
                minY = y;
            }

            if (y > maxY) {
                maxY = y;
            }
        }
        int realWidth = Math.max(maxX - minX + 1, 0);
        int realHeight = Math.max(maxY - minY + 1, 0);

        mapInfo.left = minX;
        mapInfo.top = minY;
        mapInfo.right = maxX;
        mapInfo.bottom = maxY;


        int[] data = new int[realWidth * realHeight];
        Arrays.fill(data, MapInfo.TYPE_NONE);
        for (int i = 0; i < data.length; i++) {
            int clipX = i % realWidth;
            int clipY = i / realWidth;
            data[i] = mapArray[(clipY + mapInfo.top) * mapWidth + clipX + mapInfo.left];
        }

        LogUtils.lm(data,realWidth);

        mapInfo.mapData = data;
        mapInfo.width = realWidth;
        mapInfo.height = realHeight;
        mapInfo.cleanArea = (int)cleanArea;


        LogUtils.i("map range left :" + minX + " top: " + minY + "  right: " + maxX + " bottom: " + maxY);
    }

    public static void convertPath(GyroMapInfo mapInfo, Path path, Sweeper sweeper) {
        path.destPathPoints.clear();
        int size = path.pathPoints.size();
        for (int i = 0; i < size; i++) {
            path.destPathPoints.add(new PathPoint(path.pathPoints.get(i).x - mapInfo.left, path.pathPoints.get(i).y - mapInfo.top, PathPoint.TYPE_CLEAN));
        }

        //设置扫地机位置
        if (size > 0) {
            float rotation = PathUtils.getRotationFromPath(path.destPathPoints);
            sweeper.set(path.destPathPoints.get(size - 1).x, path.destPathPoints.get(size - 1).y, rotation);
        } else {
            sweeper.set(0, 0, 0);
        }
    }

    public static void parseRecord(CleanRecord cleanRecord, byte[] cleanRecordData) {
        Map map = cleanRecord.getMap();
        GyroMapInfo gyroMapInfo = new GyroMapInfo();
        Path gyroPath = new Path();
        map.setMap(gyroMapInfo);
        map.setPath(gyroPath);

        ParseResult mapResult = GyroMapDataParser.parseMapData(map, cleanRecordData);

        LogUtils.i("YxCloud map result is" + mapResult.getCode());
        if (mapResult.getCode() != ParseResult.MSG_PARSE_SUCCESS) {
            LogUtils.i("YxCloud  map clear" + mapResult.getCode());
            map.getRoom().clear();
            map.getArea().clear();
            map.getPath().clear();
            map.getSweeper().clear();
            map.getPower().clear();
            map.getMap().mapData = null;
        }
        GyroMapInfo mapInfo = (GyroMapInfo) map.getMap();
        LogUtils.i("YxCloud record cleanArea : " + mapInfo.cleanArea);
        cleanRecord.setArea(mapInfo.cleanArea);
    }
}
